package com.yang.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jayway.jsonpath.JsonPath;
import com.yang.exception.SystemFailException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Json工具类
 * 
 * @author
 * 
 * @date 2015年1月13日
 */
public class JsonUtil {

	static Logger logger = LoggerFactory.getLogger(JsonUtil.class);

	private static ObjectMapper objectmapper = new ObjectMapper();
    /*jsonPath正则表达式*/
    private static String jsonPathRegex = "(\\$\\.(\\w*(\\[.*\\])?)(\\..*?)*)\"";

	/**
	 * 把任何对象转换成Json
	 * @param object
	 * @return Json字符串
	 */
	public static String objectToJson(Object object) {
		Writer strWriter = new StringWriter();
		try {
			objectmapper.writeValue(strWriter, object);
		} catch (Exception e) {
            logger.error("JSON解析出错",e);
		}
		String json = strWriter.toString();
		return json;
	}


    /**
     * 过滤掉空值
     * @param object
     * @return
     */
    public static String toJsonIgnoreNull(Object object) {
        Writer strWriter = new StringWriter();
        try {
            ObjectMapper mapper= new ObjectMapper();
            // 过滤对象的null属性.
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            // 过滤map中的null值
            mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
            mapper.writeValue(strWriter, object);
        } catch (Exception e) {
            logger.error("JSON解析出错:",e);
        }
        String json = strWriter.toString();
        return json;
    }



	/**
	 * 把JSON串转换成实体类
	 * 
	 * @param clazz
	 *            需要转换的实体对象class
	 * @param json
	 *            需要转换的JSON串
	 * @return 实体对象
	 */
	public static <T> T toBean(String json, Class<T> clazz) {
		try {
			return objectmapper.readValue(json, clazz);
		} catch (Exception e) {
			logger.error("JSON解析出错,错误原因:",e);
			return null;
		}
	}


    /**
     * 把JSON串转换成实体类,忽略未知字段
     *
     * @param clazz
     *            需要转换的实体对象class
     * @param json
     *            需要转换的JSON串
     * @return 实体对象
     */
    public static <T> T toBeanIgnoreUnkown(String json, Class<T> clazz) {
        try {
            ObjectMapper objectmapper = new ObjectMapper();
            objectmapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            return objectmapper.readValue(json, clazz);
        } catch (Exception e) {
            logger.error("JSON解析出错,错误原因:",e);
            return null;
        }
    }

    /**
     * 解析json中指定的key
     * @param json json
     * @param key 目标属性键值
     * @return
     */
    public static JsonNode getValue(String json, String key){
        try {
            JsonNode node = objectmapper.readTree(json);// 这里的JsonNode和XML里面的Node很像
            return node.get(key);
        } catch (IOException e) {
        	logger.error("JSON解析出错,错误原因:",e);
            throw new RuntimeException("json格式错误");
        }
    }

    /**
     * 解析json中指定的key
     * @param json json
     * @param key 目标属性键值
     * @param clazz 目标属性的类型
     * @return
     */
    public static Object getValue(String json,String key,Class clazz){
        try {
            JsonNode valueNode=getValue(json,key);
            return objectmapper.treeToValue(valueNode,clazz);
        } catch (IOException e) {
        	logger.error("JSON解析出错,错误原因:",e);
            throw new RuntimeException("json格式错误");
        }
    }

    /**
     * JsonNode转换成指定类型
     * @param jsonNode
     * @param clazz
     * @return
     */
    public static Object transfor(JsonNode jsonNode, Class clazz){
        try {
            if(jsonNode!=null){
                return objectmapper.treeToValue(jsonNode,clazz);
            }else{
                return null;
            }
        } catch (JsonProcessingException e) {
        	logger.error("类型转换错误原因:",e);
            throw new RuntimeException("类型转换错误");
        }
    }

    /**
     * JsonNode转换成指定类型
     * @param jsonNode
     * @param clazz
     * @param actualClazz
     * @return
     */
    public static Object transfor(JsonNode jsonNode, Class clazz, Class ... actualClazz){
        if(actualClazz==null){
            return transfor(jsonNode,clazz);
        }
        JavaType javaType=objectmapper.getTypeFactory().constructParametricType(clazz, actualClazz);
        try {
            return objectmapper.readValue(objectmapper.treeAsTokens(jsonNode), javaType);
        } catch (IOException e) {
            logger.error("json转换错误原因:",e);
            throw new RuntimeException("json转换错误");
        }
    }
    /**
     * 强制所有类型转为String并转为json
     * */
    public static String toJsonWithString(Map result){
        try {
            StringUtil.allAttributesToString(result);
        } catch (IllegalAccessException e) {
            logger.error("强制所有类型转为String失败,错误原因:",e);
            throw new SystemFailException("强制所有类型转为String失败");
        }
        return objectToJson(result);
    }

    /**
     * 将目标json动态添加一个属性
     * @param json
     * @param key
     * @param value
     * @return
     */
    public static String putString(String json,String key,String value){
        try {
            JsonNode node = objectmapper.readTree(json);
            ((ObjectNode)node).put(key, value);
            return node.toString();
        } catch (IOException e) {
        	logger.error("JSON解析出错,错误原因:",e);
            throw new RuntimeException("json格式错误");
        }
    }


    /**
	 *  根据传入的KEY从JSON串中取出对应的VALUE
	 * @param json
	 * @param key
	 * @return
	 */
	public static String jsonToStringByKey(String json, String key){
          try {
            JsonNode rootNode = objectmapper.readTree(json);
            String value = rootNode.path(key).asText();
            return value;
		} catch (Exception e) {
			logger.error("JSON解析出错:",e);
			return null;
		} 
	}

    public static Map toMap(String json){
        try {
            return objectmapper.readValue(json, Map.class);
        } catch (Exception e) {
            logger.error("JSON解析出错:",e);
            return null;
        }
    }

    /**
     * 解析jsonPath表达式
     * @param json 含有jsonpath表达式的字符串
     * @param context 表达式所需要的上下文环境
     * @return 返回解析后的结果
     */
    public static String parseJsonPath(String json,Map context){
        logger.info("解析json表达式开始，json：{},context:{}",json, JsonUtil.objectToJson(context));
        if(context==null||context.isEmpty()){
            return json;
        }
        Pattern pattern=Pattern.compile(jsonPathRegex);
        Matcher matcher=pattern.matcher(json);
        while(matcher.find()){
            String templat=matcher.group(1);/*匹配到整个表达式*/
            String command=matcher.group(2);/*匹配$后面的首个单词*/
            logger.info("template:{}，placeHoder:{}",templat,command);
            if(StringUtil.hasEmpty(templat, command)){
                logger.error("json表达式不合法");
                return json;
            }
            String sourceJson= JsonUtil.objectToJson(context);
            if(StringUtils.isBlank(sourceJson)){
                logger.error("上下午中缺少{}json对象",command);
                return json;
            }
            Object value= JsonPath.read(sourceJson, templat);
            if(value.getClass()==String.class){
                json=json.replace(templat,(String)value);
            }else{
                json=json.replace("\""+templat+"\"",value.toString());
            }

        }
        return json;
    }

    /**
     * 判断字符串中是否包含jsonPath表达式
     * @param json
     * @return true代表包含
     */
    public static boolean containsJsonPath(String json){
        Pattern p = Pattern.compile(jsonPathRegex);
        Matcher m = p.matcher(json);
        if(m.find()){
            return true;
        }
        return false;
    }
}
